package com.wxb.note.model;

import com.wxb.note.catty.ICatty;
import com.wxb.note.constant.PriceType;
import com.wxb.note.util.AssertUtil;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 由于涉及到金钱，表示价格使用BigDecimal
 * @author wxb
 */
public abstract class BaseFruit {
    /**
     * 单价
     */
    BigDecimal price;
    /**
     * 单价类型  默认是 斤
     */
    PriceType priceType = PriceType.HALF_A_KILOGRAM;
    /**
     * 数量/斤/公斤
     */
    BigDecimal num;
    /**
     * 折扣
     */
    BigDecimal discount;

    public BaseFruit(BigDecimal price, PriceType priceType, BigDecimal num, BigDecimal discount) {
        this.price = price;
        this.priceType = priceType;
        this.num = num;
        this.discount = discount;
    }

    public BaseFruit(BigDecimal price, PriceType priceType, BigDecimal num) {
        this.price = price;
        this.priceType = priceType;
        this.num = num;
    }

    public BaseFruit(BigDecimal price, BigDecimal num) {
        this.price = price;
        this.num = num;
    }

    /**
     * 计算价格, 父类计算，但是子类也需要实现，方便后期计算逻辑或者业务的调整
     * @return
     */
    public BigDecimal calculation(){
        if (Objects.nonNull(discount)) {
            return price.multiply(num, MathContext.DECIMAL64)
                    .multiply(discount, MathContext.DECIMAL64);
        }
        return price.multiply(num, MathContext.DECIMAL64);
    }

    public static BigDecimal multiplePriceCount(List<BigDecimal> prices) {
        BigDecimal totalPrice = new BigDecimal("0.0");
        prices = Optional.ofNullable(prices)
                .orElseGet(Collections::emptyList);

        for (BigDecimal price : prices) {
            totalPrice = totalPrice.add(price, MathContext.DECIMAL64);
        }
        return totalPrice;
    }

    public static BigDecimal multiplePriceCount(List<BigDecimal> prices, ICatty catty) {
        return catty.calculation(multiplePriceCount(prices));
    }

    void checkFieldValue(){
        AssertUtil.notNull(priceType, "单价类型");
        AssertUtil.gtZero(price, "价格");
        AssertUtil.gtZero(num, "数量");
        AssertUtil.geZeroAndLeOne(discount, "折扣");
    }

    void checkFieldValue(String fruitName){
        if (Objects.isNull(fruitName)) {
            checkFieldValue();
        }
        AssertUtil.notNull(priceType, fruitName + "单价类型");
        AssertUtil.gtZero(price, fruitName + "价格");
        AssertUtil.gtZero(num, fruitName + "数量");
        AssertUtil.geZeroAndLeOne(discount, fruitName + "折扣");
    }
}
